﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GlassHUD : MonoBehaviour {
	GameObject destination;
	public GameObject[] waypoints;
	public GameObject[] orderedNodes;

	public GameObject[] path2Nodes;
	public int[] path2Dir;

	public float minVal = .075f;
	public float maxVal = 1f;
	float soundDur = 3.57f;
	float timer;
	int counter;
	float delay;
	bool playedSonar;

	GameObject[] pathNodes;
	//GameObject[] potentialNodes;
	List<GameObject> acceptedNodes;
	List<GameObject> potentialNodes;
	CycleSounds sounds;
	GameObject audioGO;

	GameObject[] nodes;
	bool isColored;
	int found;
	int[] nodeSigns;
	int dir;
	//int[] pathDir;
	GameObject nextWaypoint;
	GameObject wp1;
	bool hasPlayed;
	int minD;
	float d1;
	//GameObject wp2;
	float d2;
	//GameObject prevWp;

	public GameObject[] restaurants;

	public GameObject leftArrow;
	public GameObject rightArrow;

	public AudioClip turnLeft;
	public AudioClip turnRight;
	public AudioClip arrivalSound;
	public int arrowDur = 60; // number of frames to display arrow
	int arrowCount;
	bool arrowActive;
	bool inTransit;
	int curr;
	int localIndex;

	// Use this for initialization
	void Start () {
		arrowActive = false;
		arrowCount = 0;
		//waypoints = GameObject.FindGameObjectsWithTag("Waypoint");
		//pathNodes = new GameObject[3];
		//potentialNodes = new GameObject[5];
		potentialNodes = new List<GameObject>();
		sounds = this.gameObject.GetComponent<CycleSounds>();
		audioGO = GameObject.FindGameObjectWithTag("NewSource");
		curr = 0;
		hasPlayed = false;
		counter = 0;
		playedSonar = false;
		localIndex = -1;
		timer = 0;
	}
	
	// Update is called once per frame
	void Update () {

		if(Input.GetKeyDown(KeyCode.Return)){
			if(sounds.getCycling()) sounds.keyOper(false);
			else sounds.keyOper(true);
		}
		if(Input.GetKeyDown(KeyCode.P)){
			printPath();
		}
		if(Input.GetKeyDown(KeyCode.Alpha1)){
			setDestination(restaurants[0]);
			sounds.keyOper(false);
			sounds.playVoiceShot(0);
			//if(!sounds.audio.isPlaying) sounds.audio.PlayOneShot(sounds.confirmationBeep);
		}
		if(Input.GetKeyDown(KeyCode.Alpha2)){
			setDestination(restaurants[1]);
			sounds.keyOper(false);
			sounds.playVoiceShot(1);
			//if(!sounds.audio.isPlaying) sounds.audio.PlayOneShot(sounds.confirmationBeep);
			//nextWaypoint = path2Nodes[0];
		}
		if(Input.GetKeyDown(KeyCode.Alpha3)){
			setDestination(restaurants[2]);
			sounds.keyOper(false);
			sounds.playVoiceShot(2);
			//if(!sounds.audio.isPlaying) sounds.audio.PlayOneShot(sounds.confirmationBeep);
		}
		if(Input.GetKeyDown(KeyCode.Alpha4)){
			setDestination(restaurants[3]);
			sounds.keyOper(false);
			sounds.playVoiceShot(3);
			//if(!sounds.audio.isPlaying) sounds.audio.PlayOneShot(sounds.confirmationBeep);
		}
		if(Input.GetKeyDown(KeyCode.Alpha5)){
			setDestination(restaurants[4]);
			sounds.keyOper(false);
			sounds.playVoiceShot(4);
			//if(!sounds.audio.isPlaying) sounds.audio.PlayOneShot(sounds.confirmationBeep);
		}

		if(arrowActive){
			arrowCount++;
		} else {
			arrowCount = 0;
		}

		if(arrowCount>=arrowDur){
			arrowsOff();
		}

		if(isColored){
			timer -= Time.deltaTime;
			if(timer<=0) decolorRestaurants();
		}

		for(int i=0; i<orderedNodes.Length; i++){
			if(!orderedNodes[i].CompareTag("Restaurant")){
				if(d (this.gameObject.transform.position,orderedNodes[i].transform.position) <= 8){
					localIndex = i;
					//Debug.Log ("LOCAL INDEX: " + localIndex);
				}
			}
		}

		if(inTransit){
			/*
			if(curr==0){
				nextWaypoint = pathNodes[0];
			}
			*/
			Vector3 currPos = new Vector3(this.gameObject.transform.position.x, 0f, this.gameObject.transform.position.z);
			Vector3 nextPos = new Vector3(nextWaypoint.gameObject.transform.position.x, 0f, nextWaypoint.gameObject.transform.position.z);

			delay = computeDistanceRatio(currPos,nextPos);
			//Debug.Log("DELAY: " + delay);
			//if(!this.audio.isPlaying) this.audio.PlayDelayed(delay);
			if(!audioGO.audio.isPlaying) audioGO.audio.PlayDelayed(delay);
			
			/*
			Debug.Log ("COUNTER MAX: " + counterMax);
			if(counter<counterMax){
				counter++;
			} else if (counter>=counterMax){
				counter = 0;
				playedSonar = false;
			}
			//Debug.Log ("Counter: " + counter);
			if(!playedSonar){
				if(!this.audio.isPlaying) this.audio.Play();
			}
			*/
			if(Vector3.Distance(currPos,nextPos)<=8){
				curr++;
				hasPlayed = false;
				arrowsOff();
				if(!nextWaypoint.CompareTag("Restaurant")){
					//if(pathNodes[curr]!=null){
					if(curr<pathNodes.Length){
						nextWaypoint = pathNodes[curr];
						Debug.Log("Next Waypoint: " +  nextWaypoint);
					} else {
						// arrival
					}
				}else{
					//arrived
				}
			} else if(Vector3.Distance(currPos,nextPos)<=12){
				/*
				Vector3 vec = this.transform.forward - nextWaypoint.transform.position.normalized;
				switch (cross(this.gameObject.transform.forward,vec)){
				case -1:
					//if(dot (this.gameObject.transform.forward,Vector3.forward)<=0) goRight();
					//else goLeft();
					goLeft();
					break;
				case 1:
					//if(dot (this.gameObject.transform.forward,Vector3.forward)<=0) goLeft();
					//else goRight();
					goRight();
					break;
				case 0:
					// forward or back
					break;
				}
				*/
				if(nextWaypoint.CompareTag("Restaurant")){
					goRight();
				} else {
					goLeft();
				}
			}
		}
	}

	void setDestination(GameObject target){
		if(destination==null){
			destination = target;
			destination.renderer.material.color = Color.blue;
			routeTo(destination);
			inTransit = true;
		} else {
			destination.renderer.material.color = Color.red;
			destination = target;
			routeTo(destination);
			inTransit = true;
			destination.renderer.material.color = Color.blue;
		}
		// calculate first waypoint...or all? 
	}

	void arrival(){
		// play arrival audio
		destination.renderer.material.color = Color.red;
		nextWaypoint = null;
		inTransit = false;
		destination = null;
	}

	void goLeft(){
		arrowActive = true;
		leftArrow.SetActive(true);
		if(!hasPlayed){
			this.audio.PlayOneShot(turnLeft);
			hasPlayed = true;
		}
	}

	void goRight(){
		arrowActive = true;
		rightArrow.SetActive(true);
		if(!hasPlayed){ 
			this.audio.PlayOneShot(turnRight);
			hasPlayed = true;
		}
	}

	void arrowsOff(){
		if(leftArrow.activeSelf) leftArrow.SetActive(false);
		if(rightArrow.activeSelf) rightArrow.SetActive(false);
		arrowActive = false;
	}

	void routeTo(GameObject target){
		acceptedNodes = new List<GameObject>();
		potentialNodes = new List<GameObject>();
		nextWaypoint = null;
		int targetIndex = 0;
		Vector3 vec = new Vector3();
		vec = this.transform.forward - target.transform.position.normalized;
		dir = dot (this.gameObject.transform.forward, vec);
		GameObject currWP;

		for(int i=0;i<orderedNodes.Length;i++){
			if(orderedNodes[i] == target) targetIndex = i;
		}

		if((targetIndex>localIndex)&&(targetIndex<orderedNodes.Length)){
			for(int i = localIndex+1; i<orderedNodes.Length; i++){
				if(!orderedNodes[i].CompareTag("Restaurant")){
					acceptedNodes.Add(orderedNodes[i]);
				}
				if(orderedNodes[i] == target){
					acceptedNodes.Add(orderedNodes[i]);
					pathNodes = acceptedNodes.ToArray();
					i = orderedNodes.Length;
				}
			}
			pathNodes = acceptedNodes.ToArray();
			nextWaypoint = pathNodes[0];
		} else if(localIndex>targetIndex){
			for(int i = localIndex+1; i<orderedNodes.Length; i++){
				if(!orderedNodes[i].CompareTag("Restaurant")){
					acceptedNodes.Add(orderedNodes[i]);
				}
			}
			for(int i=0; i<localIndex; i++){
				if(!orderedNodes[i].CompareTag("Restaurant")){
					acceptedNodes.Add(orderedNodes[i]);
				}
				if(orderedNodes[i] == target){
					acceptedNodes.Add(orderedNodes[i]);
					pathNodes = acceptedNodes.ToArray();
					i = orderedNodes.Length;
				}
			}
		}
	}

	int dot(Vector3 v1, Vector3 v2){
		Vector2 v1_2 = new Vector2(v1.x, v1.z);
		Vector2 v2_2 = new Vector2(v2.x, v2.z);
		if(Vector3.Dot(v1_2.normalized,v2_2.normalized)>0){
			return 1;
			//return -1;
		} else if(Vector3.Dot(v1_2.normalized,v2_2.normalized)<0){
			return -1;
			//return 1;
		} else {
			return 0;
		}
		/*		
		 * float result;
		result = (v1.x*v2.x)+(v1.z*v2.z);
		if(result>0){
			return 1;
		} else if(result<0){
			return -1;
		} else {
			return 0;
		}
		*/
	}
	int cross(Vector3 v1, Vector3 v2){
		//Vector2 v1_2 = new Vector2(v1.x, v1.z);
		//Vector2 v2_2 = new Vector2(v2.x, v2.z);
		float val = v1.x*v2.x-v1.z*v2.z;
		if(val>0){
			return 1;
			//return -1;
		} else if(val<0){
			return -1;
			//return 1;
		} else {
			return 0;
		}
	}

	float d(Vector3 v1, Vector3 v2){
		Vector2 v1_2 = new Vector2(v1.x, v1.z);
		Vector2 v2_2 = new Vector2(v2.x, v2.z);
		return Vector2.Distance(v1_2,v2_2);
	}

	void printPath(){
		for(int i=0; i<pathNodes.Length; i++){
			Debug.Log("NODE #" + i + ": " + pathNodes[i]);
		}
	}

	void printArr(GameObject[] arr){
		Debug.Log("PRINTING ARR: " + arr);
		for(int i=0; i<arr.Length; i++){
			Debug.Log ("INDEX: " + i + ", VALUE: " + arr[i]);
		}
	}

	float computeDistanceRatio(Vector3 v1, Vector3 v2){
		Vector3 originVec = v1;
		Vector3 targetVec = v2;
		Vector3 playerVec = this.gameObject.transform.position;
		
		float originToTarget = Vector3.Distance (originVec, targetVec);
		float ratio = originToTarget / 30;

		return minVal + ratio*maxVal;
	}

	public void colorRestaurant(int index){
		restaurants[index].renderer.material.color = Color.blue;
		isColored = true;
		timer = soundDur;
	}

	void decolorRestaurants(){
		for(int i=0;i<restaurants.Length;i++){
			restaurants[i].renderer.material.color = Color.red;
		}
		isColored = false;
	}
}
